package main

import (
	"fmt"
	"os"
	"path/filepath"
	"peilian-api/app/global/databases/tables"
	"peilian-api/utils/encrypt"
	"strings"
	"time"

	"github.com/tealeg/xlsx"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

// 学历是固定的，无需加入数据库
var EducationArr = []string{"大专", "本科", "硕士", "博士"}

// 年级固定
var GradeArr = []string{"2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023"}

var AgentId int
var PwdPrefix = "YS"

var SchoolConstituteId int
var InserSchool string

var db *gorm.DB
var err error

const (
	userName = "youshi"
	pwd      = "1G?ywxyrlis4Orl"
	ipCode   = "10.9.93.161:3306"
	dbName   = "peilian"
)

var AllUsers = make(map[string]int64)

// const (
//
//	userName = "youshi_t"
//	pwd      = "2K4adice?sdfrx3e"
//	ipCode   = "10.9.93.161:3306"
//	dbName   = "peilian_test_zs"
//
// )
func generatePwd(sno string) string {
	// 1. 根据学校名称获取学校前缀
	// 2. 生成密码
	// rsaPwd, _ := encrypt.RsaEncode(prefix + sno)
	userPwd, _ := encrypt.EncryptPassword(PwdPrefix + sno)
	return userPwd
}

func CreateDB() error {
	dbinfo := strings.Join([]string{userName, ":", pwd, "@tcp(", ipCode, ")/", dbName, "?charset=utf8&parseTime=True&loc=Local"}, "")
	db, err = gorm.Open(mysql.Open(dbinfo), &gorm.Config{
		DisableForeignKeyConstraintWhenMigrating: true,
	})
	if err != nil {
		return err
	}
	return nil
}

func ReadExcle(filepath string) [][][]string {
	out, err := xlsx.FileToSlice(filepath)
	if err != nil {
		panic(err.Error())
	}
	return out
}
func Contains(elements []string, needle string) bool {
	for _, v := range elements {
		if needle == v {
			return true
		}
	}

	return false
}

type Model struct {
	Id        uint           `gorm:"primarykey" json:"id"`
	CreatedAt time.Time      `json:"created_at" format:"2006-01-02 15:04:05"`
	UpdatedAt time.Time      `json:"updated_at"`
	DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}

type Agent struct {
	Model
}
type Constitute struct {
	Model
	Type       string `json:"type"`
	Name       string `json:"name"`
	BelongToId int    `json:"belong_to_id"`
	AgentId    int    `json:"agent_id"`
}

type Users struct {
	CreatedAt    time.Time `json:"created_at" format:"2006-01-02 15:04:05"`
	UpdatedAt    time.Time `json:"updated_at"`
	Id           int       `json:"id"`
	Name         string    `json:"name"`
	Sno          string    `json:"sno"`
	Password     string    `json:"password"`
	AccountName  *string   `json:"account_name"`
	Type         string    `json:"type"`
	School       string    `json:"school"`
	Academy      string    `json:"academy"`
	Profession   string    `json:"profession"`
	Grade        string    `json:"grade"`
	Education    string    `json:"education"`
	ConstituteID uint      `json:"constitute_id"`
	RoleId       uint      `json:"role_id"`
	AgentID      uint      `json:"agent_id"`
	Phone        string    `json:"phone"`
	Email        string    `json:"mail"`
	Level        int       `json:"level"`
}

type CommonConf struct {
	Model
	ConfKey    string `json:"conf_key" gorm:"type:varchar(20);comment:指定key"`
	Type       uint   `json:"type" gorm:"type:tinyint(3);default:0;comment:类型"`
	ConfValue  string `json:"conf_value" gorm:"type:longtext;comment:详细信息"`
	Remarks    string `json:"remarks" gorm:"type:varchar(256);default:\"\";comment:详细备注"`
	ExtendInfo string `json:"extend_info" gorm:"type:varchar(1024);default:\"\";comment:扩展信息"`
	Other      string `json:"other" gorm:"type:varchar(256);default:\"\";comment:其他信息"`
}

/*
var m map[string]int = make(map[string]int, 0)
var q map[string]map[string]int = make(map[string]map[string]int, 0)

func dealMap() {
	var c []Constitute
	db.Table("constitute").Where("type = ? and belong_to_id = ?", "academy", SchoolConstituteId).Select("id,name,type,belong_to_id").Find(&c)
	for i := 0; i < len(c); i++ {
		m[c[i].Name] = int(c[i].Id)
		if _, ok := q[c[i].Name]; !ok {
			q[c[i].Name] = make(map[string]int, 0)
		}
		var d []Constitute
		db.Table("constitute").Where("type = ? and belong_to_id = ?", "profession", c[i].Id).Select("id,name,type,belong_to_id").Find(&d)
		for j := 0; j < len(d); j++ {
			q[c[i].Name][d[j].Name] = int(d[j].Id)
		}
	}
}

func analysis(out [][][]string) {
	var errInfo = []string{}
	for i := 1; i < len(out[0]); i++ {
		name := out[0][i][0]
		sno := out[0][i][1]
		// fmt.Println(out[0][i][2]) // 无
		academy := strings.ReplaceAll(strings.ReplaceAll(out[0][i][2], "（", "("), "）", ")")
		profession := strings.ReplaceAll(strings.ReplaceAll(out[0][i][3], "（", "("), "）", ")")
		education := out[0][i][4]
		grade := out[0][i][5]
		if !Contains(GradeArr, grade) {
			errInfo = append(errInfo, sno+",grade不存在")
			continue
		}
		if !Contains(EducationArr, education) {
			errInfo = append(errInfo, sno+",学历不存在")
			continue
		}
		fmt.Println(name, academy, profession)
		var c = Constitute{}
		var count int64
		if _, ok := m[academy]; !ok {
			d := db.Table("constitute").Where("type = ? and name = ? and belong_to_id = ?", "academy", academy, SchoolConstituteId).Select("id,name,type,belong_to_id").Find(&c).Count(&count)
			if d.Error != nil {
				errInfo = append(errInfo, sno+",学院建立错误")
				continue
			}
			if count == 0 { // 插入
				c.CreatedAt = time.Now().UTC()
				c.UpdatedAt = time.Now().UTC()
				c.AgentId = 0
				c.Type = "academy"
				c.BelongToId = SchoolConstituteId
				c.Name = academy
				db.Table("constitute").Create(&c)
				if c.Id == 0 {
					errInfo = append(errInfo, sno+",学院建立错误")
					continue
				}
			}
			m[c.Name] = int(c.Id)
			q[academy] = make(map[string]int, 0)
		}
		if pid, ok := m[academy]; ok {
			if _, okq := q[academy][profession]; !okq {
				var p Constitute
				// 查询专业是否存在
				d := db.Table("constitute").Where("type = ? and name = ? and belong_to_id = ?", "profession", profession, pid).Select("id,name,type,belong_to_id").Find(&p).Count(&count)
				if d.Error != nil {
					errInfo = append(errInfo, sno+",专业建立错误")
					continue
				}
				c = Constitute{}
				var constitute_id = pid
				if count == 0 { // 插入
					c.CreatedAt = time.Now().UTC()
					c.UpdatedAt = time.Now().UTC()
					c.AgentId = 0
					c.Type = "profession"
					c.BelongToId = int(pid)
					c.Name = profession
					db.Table("constitute").Create(&c)
					if c.Id == 0 {
						errInfo = append(errInfo, sno+",专业建立错误")
						continue
					}
					constitute_id = int(c.Id)
				}
				if constitute_id == 0 {
					errInfo = append(errInfo, sno+",专业建立错误")
					continue
				}
				q[academy][profession] = int(c.Id)
			}
		}
	}
	for i := 0; i < len(errInfo); i++ {
		fmt.Println(errInfo[i])
	}

}
*/

var academyMap = make(map[string]uint)
var professionMap = make(map[string]uint)

// 创建学院专业
func CreateConstitute(academy, profession string) uint {
	academyId, ok := academyMap[academy]
	// 创建院系
	if !ok || academyId == 0 {
		var a Constitute
		db.Table("constitute").Where("type = ? and belong_to_id = ? and name = ?", "academy", SchoolConstituteId, academy).Select("id,name,type,belong_to_id").Find(&a)
		if a.Id == 0 {
			a = Constitute{Name: academy, Type: "academy", BelongToId: SchoolConstituteId}
			err = db.Table("constitute").Create(&a).Error
			if err != nil {
				panic(err)
			}
		}
		academyMap[academy] = a.Id
		academyId = a.Id
	}
	key := fmt.Sprintf("%s-%d", profession, academyId)
	pId, ok := professionMap[key]
	// 创建专业
	if !ok || pId == 0 {
		var p Constitute
		db.Table("constitute").Where("type = ? and belong_to_id = ? and name = ?", "profession", academyId, profession).Select("id,name,type,belong_to_id").Find(&p)
		if p.Id == 0 {
			p = Constitute{Name: profession, Type: "profession", BelongToId: int(academyId)}
			err = db.Table("constitute").Create(&p).Error
			if err != nil {
				panic(err)
			}
		}
		pId = p.Id
		professionMap[key] = pId
	}
	//fmt.Println(academyId, pId)
	return pId
}

func GetCurrentUsers() {
	var users []Users
	db.Table("users").Where("school = ?", InserSchool).Select("id,name,sno").Find(&users)
	for i := 0; i < len(users); i++ {
		AllUsers[users[i].Sno] = int64(users[i].Id)
	}
}

// 导入学生
func insertStudent(out [][][]string) {
	var users []Users
	for s := 0; s < len(out); s++ {
		for i := 1; i < len(out[s]); i++ {
			if len(out[s][i]) < 6 {
				fmt.Println(s, i, out[s][i])
				continue
			}
			name := out[s][i][0]
			sno := out[s][i][1]
			academy := out[s][i][2]
			profession := out[s][i][3]
			education := out[s][i][4]
			grade := out[s][i][5]
			//constitute_id := q[academy][profession]
			// 创建学院和专业
			constitute_id := CreateConstitute(academy, profession)
			if AllUsers[sno] != 0 {
				fmt.Println(sno, "已存在")
				continue
			}
			AllUsers[sno] = 1

			var user Users
			user.CreatedAt = time.Now().UTC()
			user.UpdatedAt = time.Now().UTC()
			user.Name = name
			user.Type = "normal"
			user.School = InserSchool
			user.Academy = academy
			user.Profession = profession
			user.Grade = grade
			user.AgentID = uint(AgentId)
			user.RoleId = 0
			user.Sno = sno
			user.Level = 0
			user.ConstituteID = constitute_id
			user.Education = education
			user.Password = generatePwd(sno)
			// db.Table("users").Save(&user)
			users = append(users, user)
			if len(users) == 50 {
				db.Table("users").Model(&user).CreateInBatches(users, len(users))
				users = []Users{}
				fmt.Println(s, i)
			}
			// db.Table("users").Where("sno = ? and school = ?", sno, InserSchool).FirstOrCreate(&user)
			// fmt.Println(user)
			// break
		}
	}
	if len(users) > 0 {
		db.Table("users").CreateInBatches(users, len(users))
	}
}

func main() {
	CreateDB()
	dir, _ := os.Getwd()
	filePath := dir + "/scripts/school/beihang/无锡商业职业技术学院.xlsx"
	InserSchool = strings.Split(filepath.Base(filePath), ".")[0]
	InserSchool = strings.Split(InserSchool, "_")[0]

	// 获取agent_id
	var agent Agent
	db.Table("agent").Where("agent_name = ? ", InserSchool).Select("id").Find(&agent)
	if agent.Id == 0 {
		panic("agent_id不存在")
	}
	AgentId = int(agent.Id)
	fmt.Println(AgentId)
	GetCurrentUsers()
	fmt.Println(len(AllUsers))
	return

	// 获取id
	//var school tables.School
	//db.Table("school").Where("name = ?", InserSchool).Select("id,name").Find(&school)
	//if school.ID != 0 {
	//	SchoolConstituteId = int(school.ID)
	//}
	// 创建密码后缀的记录

	if PwdPrefix != "" {
		var conf CommonConf
		db.Table("common_conf").Where("conf_key = ? and remarks = ?", "school", InserSchool).Select("id").Find(&conf)
		if conf.Id == 0 {
			conf = CommonConf{
				ConfKey:    "school",
				Type:       1,
				ConfValue:  PwdPrefix,
				Remarks:    InserSchool,
				ExtendInfo: "密码前缀",
			}
			err = db.Table("common_conf").Create(&conf).Error
			if err != nil {
				panic(err)
			}
		}
	}

	var constitute tables.Constitute
	db.Table("constitute").Where("name = ?", InserSchool).Select("id,name").Find(&constitute)
	if constitute.ID != 0 {
		SchoolConstituteId = int(constitute.ID)
	}

	s := ReadExcle(filePath)
	//fmt.Println(s)
	//dealMap()
	// analysis(s)
	// dealMap()
	insertStudent(s)
}
